#pragma once
/**
 * @file Poller.hpp
 * @author 1102403684@qq.com
 * @brief 通过epoll对描述符进行IO事件监控
 * @version 0.1
 * @date 2024-10-03
 *
 * @copyright Copyright (c) 2024
 *
 */


#define MAX_EPOLLEVENTS 1024
#include <unordered_map>
#include <sys/epoll.h>
#include "Channel.hpp"
#include "../common/logger.hpp"

class Poller
{
public:
    Poller()
    {
        epfd_ = epoll_create(1);
        if (epfd_ < 0)
        {
            LOG_ERROR("epoll create失败");
            abort();
        }

        LOG_TRACE("epoller 创建成功 占用fd {}", epfd_);
    }

    void update_event(Channel *channel)
    {
        bool ret = has_channel(channel);
        channels_.insert(std::make_pair(channel->get_fd(), channel));
        if (!ret)
        {
            return update_epoll(channel, EPOLL_CTL_ADD);
        }
        return update_epoll(channel, EPOLL_CTL_MOD);
    }
    bool remove_event(Channel *channel)
    {
        auto it = channels_.find(channel->get_fd());
        if (it == channels_.end())
        {
            LOG_DEBUG("remove_event失败");
            return false;
        }
        int DEBUG_fd = channel->get_fd();
        channels_.erase(channel->get_fd());
        // update_epoll(channel, EPOLL_CTL_DEL);
        /**修改一下这里 */
        int ret = epoll_ctl(epfd_, EPOLL_CTL_DEL, channel->get_fd(), nullptr);
        if(ret < 0){
            LOG_ERROR("epoll del error! {}",channel->get_fd());
        }
        return true;
    }
    void poll(std::vector<Channel*>* active)
    {
        int nfds = epoll_wait(epfd_, evs_, MAX_EPOLLEVENTS, -1);
        if (nfds < 0)
        {
            if (errno == EINTR)
            {
                return;
            }
            LOG_ERROR("epoll wait error : {}", strerror(errno));
            abort();
        }

        for (int i = 0; i < nfds; i++)
        {
            auto it = channels_.find(evs_[i].data.fd);
            assert(it != channels_.end());
            it->second->set_revents(evs_[i].events);
            active->push_back(it->second);
        }
    }

private:
    void update_epoll(Channel *channel, int op)
    {
        int fd = channel->get_fd();
        struct epoll_event ev;
        ev.data.fd = fd;
        ev.events = channel->get_events();
        int ret = epoll_ctl(epfd_, op, fd, &ev);
        if (ret < 0)
        {
            LOG_ERROR("epoll_ctl发生错误");
            abort();
        }
        return;
    }
    bool has_channel(Channel *channel)
    {
        auto it = channels_.find(channel->get_fd());
        if (it == channels_.end())
        {
            return false;
        }
        return true;
    }

private:
    int epfd_;
    struct epoll_event evs_[MAX_EPOLLEVENTS];
    std::unordered_map<int /*fd*/, Channel *> channels_;
};


